﻿/*
 * Created by: Ahmedzhanov Nail,400,438534,,J2EE
 * Created: Tuesday, March 27, 2007
 */

using System;
using Dune.Business.Domain.Base;
using Dune.Business.Domain.Users;
using Dune.Business.Security;
using Dune.Common.Services;
using Dune.DAL.Common.SessionManagment;
using NHibernate;
using NHibernate.Type;

namespace Dune.DAL.Managers
{
    public class SessionInterceptor : BaseManager, IInterceptorProvider
    {
        private Interceptor interceptor;


        public SessionInterceptor()
        {
            interceptor = new Interceptor(this);

        }

        public bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState,
                                          string[] propertyNames, IType[] types)
        {
            IStat stat = entity as IStat;
            if (stat != null)
            {
                FlushMode old = Session.FlushMode;
                Session.FlushMode = FlushMode.Commit;

                try
                {
                    EntityState entityState = new EntityState(currentState, propertyNames);

                    // TODO check for modifications
                    entityState["ModifyDate"] = DateTime.Now;
                    entityState["ModifiedBy"] = GetCurrentPerson();

                    return true;
                }
                finally
                {
                    Session.FlushMode = old;
                }

            }
            return false;
        }

        public bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
        {
            IStat stat = entity as IStat;
            if (stat != null)
            {
                FlushMode old = Session.FlushMode;
                Session.FlushMode = FlushMode.Commit;

                try
                {
                    EntityState entityState = new EntityState(state, propertyNames);

                    User person = null;

                    person = GetCurrentPerson();

                    if (IsNewObject(entity))
                    {
                        entityState["CreateDate"] = DateTime.Now;
                        entityState["CreatedBy"] = person;
                    }

                    // TODO check for modifications
                    entityState["ModifyDate"] = DateTime.Now;

                    entityState["ModifiedBy"] = person;

                    return true;
                }
                finally
                {
                    Session.FlushMode = old;
                }

            }

            return false;
        }

        private User GetCurrentPerson()
        {
            User person;
            if (Locator.GetService<IPersonManager>().IsDefinedCurrentPerson())
                person = Locator.GetService<IPersonManager>().GetCurrentPerson();
            else
                person = Locator.GetService<IPersonManager>().GetDefaultPerson();
            return person;
        }

        class EntityState
        {
            private object[] state;
            private string[] propertyNames;


            public EntityState(object[] state, string[] propertyNames)
            {
                this.state = state;
                this.propertyNames = propertyNames;
            }

            public object this[string propertyName]
            {
                get
                {
                    return state[FindIdx(propertyName)];
                }
                set
                {
                    state[FindIdx(propertyName)] = value;
                }
            }

            protected int FindIdx(string propertyName)
            {
                int idx = Array.IndexOf(propertyNames, propertyName);
                if (idx == -1)
                    throw new ArgumentException("property does not exists " + propertyName);
                return idx;
            }
        }

        #region IInterceptorProvider Members

        public IInterceptor GetInterceptor(ISessionFactory factory)
        {
            return interceptor;
        }

        #endregion
    }

    class Interceptor : EmptyInterceptor
    {
        private readonly SessionInterceptor sessionInterceptor;


        public Interceptor(SessionInterceptor sessionInterceptor)
        {
            if (sessionInterceptor == null)
                throw new ArgumentException("sessionInterceptor");
            this.sessionInterceptor = sessionInterceptor;
        }

        public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
        {
            return sessionInterceptor.OnSave(entity, id, state, propertyNames, types);
        }


        public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState,
                                          string[] propertyNames, IType[] types)
        {
            return sessionInterceptor.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
        }

    }

}